




package com.drumbeatinsight.controls {
	
	import com.drumbeatinsight.html.HTMLChild;
	import com.drumbeatinsight.html.HTMLElement;
	import com.drumbeatinsight.managers.HTMLManager;
	import com.drumbeatinsight.utils.CallLater;
	
	import flash.display.DisplayObjectContainer;
	import flash.display.InteractiveObject;
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.external.ExternalInterface;
	import flash.geom.Point;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.utils.Timer;
	
	import mx.controls.TextArea;
	import mx.core.Application;
	import mx.core.UITextField;
	import mx.events.FlexEvent;
	import mx.events.MoveEvent;
	import mx.events.ResizeEvent;
	import mx.events.ScrollEvent;
	import mx.events.ScrollEventDetail;
	import mx.styles.CSSStyleDeclaration;
	import mx.styles.StyleManager;
	
	/**
	Issues and Bugs

	- html element may overlay swf Application scrollbars if they appear.
		- developer can prevent this by checking or restricting dimensions

 	- html is always top element. can overlap other flex components
 		- created new HTMLManager alert method to show above all page elements
		- you can create a HTML instance on the application and populate it with a swf
		- developer can prevent this by manually hiding and showing the html element or html component htmlVisibility or visible
		- added method to HTMLManager to hideAllVisibleElements temporarily 
		- prevent this by making sure HTML instance is set to 100% width and or height
		- prevent this by not setting the height of the container
		- a second level of mask support may fix some occurances but is a lot of work and may not even be possible due to browser security 
	
	- when using wmode=opaque or transparent non us characters are not properly sent to the swf
		- for Firefox - fix might make it into Firefox 3.1, if not then 3.2. 
		- for Flash Player - fix was made. might be in next update or next version of Flash Player
		- https://bugs.adobe.com/jira/browse/SDK-12420
		- https://bugzilla.mozilla.org/show_bug.cgi?id=347185
		- https://bugzilla.mozilla.org/show_bug.cgi?id=272847

 
	ver 4.2
	- updated contentTop and contentLeft to include the application scroll bar position
	- focus on a text input is not given to the flex application when an iframe with a textbox has the focus
		- added new property fixTextFieldFocus to fix this 
		- https://bugs.adobe.com/jira/browse/SDK-12377
	- updated defocus to use instance id
	- updated defocus to be called when application is clicked
	- set default values for the following properties and styles, 
		tabEnabled="false" editable="false" focusThickness="0"
	- added HTMLManager.alert method to show an alert above everything on the page
	- added HTMLManager.getComponentById() method. returns html instance by id
	- added HTMLManager.getAllComponents() method. returns list of all html instances
	- added HTMLManager.remove() method. removes html instance from the stage and html items list
	- added HTMLManager.hideVisibleElements(). hides all visible HTML elements
	- added HTMLManager.showVisibleElements(). displays all html elements hidden by hideVisibleElements() call
	- added HTMLManager.enablePromptOnUnload property. enables or disables prompting when navigating away from the page
	- added HTMLManager.windowDockVisibility to set the dock visibility. don't use the dock (its html). create a dock in flex.
		added example in new features project
	- added all pop up window options to HTMLManager such as close, minimize, maximize, restore, etc
	- updated code in the positioning logic. uses localToGlobal and point object instead of previous method
	- added support for transparent backgrounds in div's
	- added xinha editor support
	- added state support - shows or hides properly when navigating through states
	- can load javascript files into the global scope - use headerIncludes property to point to js files
	- can load stylesheets dynamically - use the stylesheets property to point to css files
	- font color is now passed to div
	- font color is now inherited from the parent container

	
	ver 4.0
	- added event metadata for htmlPopUpClose
	- added event metadata for htmlPopUpMinimize
	- added event metadata for htmlPopUpMaximize
	- added event metadata for htmlPopUpCloseComplete
	- added event metadata for htmlPopUpRestore
	- added event metadata for htmlPopUpFocus
	- added event metadata for htmlPopUpResize
	- added event metadata for htmlUnload
	- added static constants for html pop up windows	
	- added weak listeners to all event listeners
	- added isSelected check to prevent prerendering in viewstacks
	- removing component from the display list when creating "HTML" pop up windows
	- dispatching events for "HTML" pop up windows
	- added relative movie property. correctly positions the html element when the swf is not in the upper left hand corner
	- added promptOnUnload option to let developer prompt user if they try to navigate away from the page in the browser
	- added promptOnUnload message option to display a custom message to the user
	- added additional callbacks to support HTML pop up windows
	- added popUpModal option to show HTML modal pop up
	- added popUpChrome option to display a pop up with HTML chrome not Flex border chrome
	- added popUpTitle to set the HTML pop up window title
	- removed functions hideByContainer and showByContainer not used
	- added code to always hide the component if asked for
	- added showLater() and hideLater() methods and made them public
	- added addCallbacks to htmlManager
	- added Alert listener to temporarily hide html elements when alert is shown
	- refactored html manager callback dispatch methods

	ver 3.2 
	fixed - support for visible false caused html not to be rendered at all
	
	ver 3.1
	fixed - support for visible false
 
	ver 3.0
	added - reference to HTMLManager in component.htmlManager property
	added - items property on htmlManager that contains an array collection of html components
	added - added event declarations at top of class
	added - external callback to swf.onPageCreationComplete(). dispatches "onLoadComplete" event. not implement in this release
	added - removeListeners method. removes listeners setup in creation complete event.
	added - insidePopUp property. is true if component is inside of a pop up window.
	added - removeElementOnRemove property. if true element is removed from the dom. if false element is hidden.
	added - removeElement() method. removes element from the dom. 
	added - refreshElement() method. resize and reposition. if the first arguement is true then rerender / overwrite the HTML element. 
	
	changed - changed from mxml class to as3 class - html.as
	changed - prefixed javascript function names with "fc" to avoid name collisions 
	
	fixed - htmlCreationComplete was not called for HTML Components without id's. IE created dynamically in pop ups 
	fixed - html element will now correctly be removed when pop up window is closed. 
	
	ver 2.2
	added - callback when element is created (division and iframe may not be completely accurate - test with your application)
	added - can add dynamic includes. can now include js files. may not work as expected when js is not on your site. test with your html. 
	added - includes can be called before or after html element is created using includesBefore and includesAfter
	added - embedded javascript support. called after element has been created.
	added - renderAtStartup. prevents rendering of component. call render to render html element. 
	added - render method. call to render html element again. rewrite over the original.
	added - call method. used to call javascript expression.
	added - editorType property. used to define a different editor. 
	added - refresh method. reexamines the location and size and rerenders if first param is true.
	added - setPosition - sets the location and size of the html element.
	added - setDocumentTitle - sets the title of the HTML page in the browser.
	
	updated - rich text editor now uses the includesBefore tag. see example.
	
	fixed - when application / browser resized the html frame would be hidden. 
	
	ver 2.0
	fixed - does not calculate correct html div position when using up and down arrows in application scrollbars
	fixed - does not calculate correct html div position when app is scrolling and in container	
	fixed - does not stay hidden when in viewstack 2 levels deep
	fixed - would throw an error when setting fitToContentHeight to true in mxml
	
	added - clearHTMLText - clears the html text on a successful load. gets rid of flicker when showing or hiding
	added - support for FCKEditor
	added - getHTML method to get div.innerHTML or FCKEditor XHTML content 
	*/

	/**
	 *  Dispatched when getElementHeight returns -1. 
	 *	This can be because the element has not been rendered completely. 
	 *	Check the htmlCreationComplete event, fitToContentHeightComplete event or wait a frame.
	 *	
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="heightFault", type="flash.events.Event")]

	/**
	 *  Dispatched when a user clicks a button in an html Alert.
	 *  The popUpAlertValue contains the button the user clicked 
	 *
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlAlertHandler", type="flash.events.Event")]

	/**
	 *  Dispatched when the html element has been added to the HTML DOM.
	 *  The html element may not be completely rendered at this point. 
	 *
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlInitialize", type="flash.events.Event")]
	
	/**
	 *  Dispatched when the html element has been created. 
	 *  In a division  event is dispatched directly after a division is created, 
	 *	in an iframe it is dispatched when the iframe onload is complete and
	 *	when an editor is created it is dispatched in the editors creation complete event.
	 *
	 *	When using the includesBefore and includesAfter the event may not be accurate. 
	 *	Test with your application and use a timer or callLater method if needed.
	 * 
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlCreationComplete", type="flash.events.Event")]
	
	/**
	 *  When the fitToContentHeight property is set to true then a timer is run. 
	 *  When that timer has completed this event is called. 
	 *
	 *  <p>At this point, depending on its <code>visible</code> property,
	 *  the component may not be visible even though it has been drawn.</p>
	 *
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="fitToContentHeightComplete", type="flash.events.Event")]
	
	/**
	 *  Dispatched when the htmlText property changes. 
	 *	
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlTextChanged", type="flash.events.Event")]
	
	/**
	 *  Dispatched when the set htmlScrollPolicy changes.
	 *	
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlScrollPolicyChanged", type="flash.events.Event")]
	
	/**
	 *  Dispatched when the source changes.
	 *	
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="sourceChanged", type="flash.events.Event")]
	
	/**
	 *  Dispatched when html pop up window closes.
	 *	
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlPopUpClose", type="flash.events.Event")]
	
	/**
	 *  Dispatched when html pop up window is minimized.
	 *	
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlPopUpMinimize", type="flash.events.Event")]
	
	/**
	 *  Dispatched when html pop up window is maximized.
	 *	
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlPopUpMaximize", type="flash.events.Event")]
	
	/**
	 *  Dispatched when html pop up window is close complete
	 *	
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlPopUpCloseComplete", type="flash.events.Event")]
	
	/**
	 *  Dispatched when html pop up window is restore
	 *	
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlPopUpRestore", type="flash.events.Event")]
	
	/**
	 *  Dispatched when html pop up window gains focus
	 *	
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlPopUpFocus", type="flash.events.Event")]
	
	/**
	 *  Dispatched when html pop up window is resized 
	 *	
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlPopUpResize", type="flash.events.Event")]
	
	/**
	 *  Dispatched when html unload event is called on iframe
	 *	
	 *  @eventType com.drumbeatinsight.controls.HTML
	 */
	[Event(name="htmlUnload", type="flash.events.Event")]
	
	//--------------------------------------
	//  Excluded APIs - exclude from auto complete
	//--------------------------------------
	
	[Exclude(name="_bindingsBeginWithWord", kind="property")]
	[Exclude(name="_bindingsByDestination", kind="property")]
	
	
	/**
	 *  The HTML Component is a wrapper for a HTML Division or IFrame element. 
	 *  The HTML Component supports the HTML rendering capabilities
	 *  of the browser it is run in.
	 *
	 *  <p>You can set the contents of the HTML control using the htmlText property 
	 * 	or the source property. The elementType property determines if the element created 
	 *  is a div or an iframe. The iframe uses the source property while the div uses the htmlText 
	 *  property. </p>
	 *
	 *  @mxml
	 *
	 *  <p>The <code>&lt;fc:HTML Component&gt;</code> tag inherits the attributes
	 *  of its superclass and adds the following attributes:</p>
	 *
	 *  <pre>
	 *  &lt;fc:HTML
	 *    <b>Properties</b>
	 *    condenseWhite="false|true"
	 *    data="undefined"
	 *    displayAsPassword="false|true"
	 *    editable="true|false"
	 *    horizontalScrollPolicy="auto|on|off"
	 *    horizontalScrollPosition="0"
	 *    htmlText="null"
	 *    imeMode="null"
	 *    length="0"
	 *    listData=null
	 *    maxChars="0"
	 *    restrict="null"
	 *    selectionBeginIndex="0"
	 *    selectionEndIndex="0"
	 *    styleSheet="null"
	 *    text=""
	 *    textHeight="<i>height of text</i>""
	 *    textWidth="<i>width of text</i>"
	 *    verticalScrollPolicy="auto|on|off"
	 *    verticalScrollPosition="0"
	 *    wordWrap="true|false"
	 *    &nbsp;
	 *    <b>Events</b>
	 *    heightFault="<i>No default</i>"
	 *    htmlInitialize="<i>No default</i>"
	 *    htmlCreationComplete="<i>No default</i>"
	 *    fitToContentHeightComplete="<i>No default</i>"
	 *    htmlTextChanged="<i>No default</i>"
	 *    htmlScrollPolicyChanged="<i>No default</i>"
	 *    sourceChanged="<i>No default</i>"
	 *    pageCreationComplete="<i>No default</i>"
	 *    removeElement="<i>No default</i>"
	 *  /&gt;
	 *  </pre>
	 *
	 *  @see mx.controls.TextArea 
	 *
	 *
	 */
	public class HTML extends TextArea {
		
	    public static const IFRAME:String = "iframe";
	    public static const DIVISION:String = "division";
	    public static const EDITOR:String = "editor";
	    public static const SHOW:String = "fcShow";
	    public static const HIDE:String = "fcHide";
	    public static const SIZE:String = "fcSetSizeByValue";
	    public static const MOVE:String = "fcSetPosition";
	    public static const REMOVE:String = "fcRemove";
	    public static const SOURCE:String = "fcSetSource";
	    public static const SET_CLIP:String = "fcSetClip";
	    public static const SET_HTML_TEXT:String = "fcSetHTML";
	    public static const GET_HTML_TEXT:String = "fcGetHTML";
	    public static const SET_VISIBILITY:String = "fcSetVisibility";
	    public static const ADD:String = "fcAddChild";
	    public static const HTML_SCROLL_POLICY:String = "fcSetScrollPolicyById";
	    public static const GET_HEIGHT:String = "fcGetElementHeight";
	    public static const GET_PROPERTY_VALUE:String = "fcGetElementValue";
	    public static const SET_DOCUMENT_TITLE:String = "fcSetDocumentTitle";
	    public static const CALL_EXPRESSION:String = "fcCallScript";
	    public static const LOAD_INCLUDES:String = "fcGetIncludes";
	    public static const CSS_INCLUDES:String = "fcGetStyleSheets";
		public static const PROMPT_ON_UNLOAD:String = "fcPromptOnUnload";
		public static const RELATIVE_MOVIE:String = "fcSetRelativeMovie";
		public static const DEFOCUS:String = "fcDefocus";
		public static const IS_BROWSER_IE:String = "fcIsIE";
		
		// html pop up window methods
		public static const CASCADE_WINDOWS:String = "fcCascadeWindows";
		public static const CLOSE_WINDOW:String = "fcCloseWindow";
		public static const CLOSE_WINDOWS:String = "fcCloseWindows";
		public static const FOCUS_WINDOW:String = "fcFocusWindow";
		public static const MAXIMIZE_WINDOW:String = "fcMaximizeWindow";
		public static const MAXIMIZE_WINDOWS:String = "fcMaximizeWindows";
		public static const MINIMIZE_WINDOW:String = "fcMinimizeWindow";
		public static const MINIMIZE_WINDOWS:String = "fcMinimizeWindows";
		public static const RESTORE_MINIMIZED_WINDOW:String = "fcRestoreMinimizedWindow";
		public static const RESTORE_WINDOW:String = "fcRestoreWindow";
		public static const TOGGLE_WINDOW_DOCK:String = "fcToggleDock";
		public static const SET_WINDOW_DOCK_VISIBILITY:String = "fcSetDockVisibility";
		
		// html pop up window events
		public static const HTML_POP_UP_CLOSE:String = "htmlPopUpClose";
		public static const HTML_POP_UP_CLOSE_COMPLETE:String = "htmlPopUpCloseComplete";
		public static const HTML_POP_UP_CONTENT_LOADED:String = "htmlPopUpContentLoaded";
		public static const HTML_POP_UP_FOCUS:String = "htmlPopUpFocus";
		public static const HTML_POP_UP_MINIMIZE:String = "htmlPopUpMinimize";
		public static const HTML_POP_UP_MAXIMIZE:String = "htmlPopUpMaximize";
		public static const HTML_POP_UP_RESIZE:String = "htmlPopUpResize";
		public static const HTML_POP_UP_RESTORE:String = "htmlPopUpRestore";
		
		/**
		 * Used to dispatch events from javascript 
		 * The pageCreationComplete event is still unreliable in certain circumstances. Test with your application.
		 * You can get a list of all html components with the component.htmlManager.items array collection.
		 * */
		public var htmlManager:HTMLManager = HTMLManager.getInstance();
		
		public function HTML() {
			super();
			
			addEventListener(FlexEvent.CREATION_COMPLETE, creationHandler, false, 0.0, true);
			htmlManager = HTMLManager.getInstance();
			
			// set default properties here
			tabEnabled = false;
			editable = false; 
		}
		
		// Define a static variable to define our default styles
        private static var classConstructed:Boolean = classConstruct();
        
        // define default styles
        private static function classConstruct():Boolean {
            if (!StyleManager.getStyleDeclaration("HTML")) {
                // If there is no CSS definition for HTML
                // then create one and set the default value.
                var newStyleDeclaration:CSSStyleDeclaration = new CSSStyleDeclaration();
                
				// set default styles here
                newStyleDeclaration.setStyle("focusThickness", "0");

                StyleManager.setStyleDeclaration("HTML", newStyleDeclaration, true);
            }
            return true;
        }
        
		private function creationHandler(event:Event):void {
			var bCreateHTMLElement:Boolean = _externalInterfaceFunction(ExternalInterface.available);
			
		    // let user cancel creation of html element
			if (bCreateHTMLElement) {
				init();
			} else {
			    // Handle failure here.
			    htmlCreated = false;
			}
		}
		
	    /**
	     *  @private
	     */
	    override protected function createChildren():void {	
	        super.createChildren();
			
			addListeners();
	    }
	    
	    /**
	    * add listeners to handle movement, positioning, resizing, etc
		*/
		public function addListeners():void {
			
			Application.application.addEventListener(FlexEvent.UPDATE_COMPLETE, applicationResize, false, 0.0, true);
			
			super.addEventListener(MoveEvent.MOVE, htmlMoveHandler, true, 0.0, true);
			super.addEventListener(ResizeEvent.RESIZE, htmlResizeHandler, false, 0.0, true);
			super.addEventListener(ResizeEvent.RESIZE, htmlResizeHandler, true, 0.0, true);
			super.addEventListener(FlexEvent.SHOW, showHandler, false, 0.0, true);
			addEventListener(FlexEvent.HIDE, hideHandler, false, 0.0, true);
			// handle states
			super.addEventListener(Event.ADDED_TO_STAGE, showHandler, true, 0.0, true);
			super.addEventListener(Event.REMOVED_FROM_STAGE, hideHandler, false, 0.0, true);
			
			var repeatCount:int = Math.ceil(getHeightTimeout/getHeightInterval);
			
	        // creates a new Timer
	        getHeightTimer = new Timer(getHeightInterval,repeatCount);
	        
	        // designates listeners for the interval and completion events
	        getHeightTimer.addEventListener(TimerEvent.TIMER, onGetHeightTick, false, 0.0, true);
	        getHeightTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onGetHeightComplete, false, 0.0, true);
	        
	        var objParent:InteractiveObject = parent;
	        var currObj:InteractiveObject = objParent;
	    	
	    	// check all parent containers of this component and add event listeners
	        while (currObj) {
	        	
	            if (currObj.parent) {
	                objParent = currObj.parent;
	            }
	            else {
	                objParent = null;
	            }
	            
				currObj.addEventListener(ScrollEvent.SCROLL, htmlScrollHandler, false, 0.0, true);
				currObj.addEventListener(MoveEvent.MOVE, htmlMoveHandler, false, 0.0, true);
				currObj.addEventListener(FlexEvent.HIDE, htmlVisibleHandler, false, 0.0, true);
				currObj.addEventListener(FlexEvent.SHOW, htmlVisibleHandler, false, 0.0, true);
				//currObj.addEventListener(FlexEvent.RESIZE, htmlResizeHandler);
				//currObj.addEventListener(ResizeEvent.RESIZE, htmlResizeHandler);
				
				// for pop ups
				// see note on removeHandler
				if (currObj.hasOwnProperty("isPopUp")) {
					insidePopUp = currObj['isPopUp'];
				}
				currObj.addEventListener(Event.REMOVED_FROM_STAGE, removeHandler, false, 0.0, true);
	   
	            currObj = objParent;
	        }
	        
	        // force fix text field assignment to add to parentApplication
	   		if (_fixTextFieldFocus) {
				Application.application.addEventListener(FocusEvent.FOCUS_IN, onFocusIn, false, 0, true);
				Application.application.addEventListener(MouseEvent.CLICK, onFocusIn, false, 0, true);
	   		}
	        
			// check if user wants to fit component to height of content
			if (!fitToContentHeight) return;
	
	        // starts the timer ticking
	        getHeightTimer.start();
			fitToElementHeight()
		}
		
		/**
		 * Remove listeners that handle movement, positioning, resizing, etc
		 * */
		public function removeListeners():void {
			
			Application.application.removeEventListener(FlexEvent.UPDATE_COMPLETE, applicationResize, false);
			
			super.removeEventListener(MoveEvent.MOVE, htmlMoveHandler, true);
			super.removeEventListener(ResizeEvent.RESIZE, htmlResizeHandler, false);
			super.removeEventListener(ResizeEvent.RESIZE, htmlResizeHandler, true);
			super.removeEventListener(FlexEvent.SHOW, showHandler, false);
			removeEventListener(FlexEvent.HIDE, hideHandler, false);
			
	        // designates listeners for the interval and completion events
	        getHeightTimer.removeEventListener(TimerEvent.TIMER, onGetHeightTick);
	        getHeightTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, onGetHeightComplete);
	        
	        var objParent:InteractiveObject = parent;
	        var currObj:InteractiveObject = objParent;
	    	
	    	// check all parent containers of this component and add event listeners
	        while (currObj) {
	        	
	            if (currObj.parent) {
	                objParent = currObj.parent;
	            }
	            else {
	                objParent = null;
	            }
	            
				currObj.removeEventListener(ScrollEvent.SCROLL, htmlScrollHandler);
				currObj.removeEventListener(MoveEvent.MOVE, htmlMoveHandler);
				currObj.removeEventListener(FlexEvent.HIDE, htmlVisibleHandler);
				currObj.removeEventListener(FlexEvent.SHOW, htmlVisibleHandler);
				
				currObj.removeEventListener(Event.REMOVED_FROM_STAGE, removeHandler);
	   
	            currObj = objParent;
	        }
	        
	        if (fixTextFieldFocus) {
	        	Application.application.removeEventListener(FocusEvent.FOCUS_IN, onFocusIn);
	   			Application.application.removeEventListener(MouseEvent.CLICK, onFocusIn);
	        }
		}
		
		private var urlLoader:URLLoader = new URLLoader();
		private var urlRequest:URLRequest;
		private var includesLeft:int = 0;
		private var includes:Array = [];
		
		public var focusAlpha:Number = 0;
	
		private function init():void {
			
			// place in the HTML Manager for our callback functions
			// we also give it an id if it does not have one in the add method
			HTMLManager.add(this);
			
			// we create public methods that javascript can call
			addHTMLCallBacks();
		    
		    // start loading include files
		    // this feature is mostly useless since scripts have their own separate scope
		    // there may be changes in the future that make this viable
		    // UPDATE added headerIncludes that load into the html head -
		    loadIncludes();
		    
		    // load js includes into the browser cache
		    // once they are downloaded our element can use them
		    // -- actually not sure if this is happening
		    // we need to find a cross browser way to determine when scripts are loaded and elements created
			var includesTotal:Number = includesBefore.length;
			includesLeft = includesTotal;
			includes = includesBefore;
			var len:int = includes.length;
			
			// check for IE
			isBrowserIE = ExternalInterface.call(IS_BROWSER_IE);
			
			if (len >0) {
				urlLoader = new URLLoader();
				urlLoader.addEventListener(Event.COMPLETE, dataLoaded, false, 0.0, true);
				urlLoader.addEventListener(IOErrorEvent.IO_ERROR, errorRetrieving, false, 0.0, true);
				urlLoader.load(new URLRequest(includesBefore[0]));
			}
			else {
                if (renderAtStartup && isSelected()) {
					render();
				}
				else if (!renderAtStartup) {
					super.visible = false;
				}
			}
		}
	    
	    // cannot load includes handler
		private function errorRetrieving(evt:IOErrorEvent):void {
	    	dispatchEvent(new IOErrorEvent(evt.type, evt.bubbles, evt.cancelable, evt.text));
	    	
			try {
				//CursorManager.removeBusyCursor();    
			}
			catch(e:Error){
				
			}
		}
		
		public function loadIncludes():void {
			if (headerIncludes.length > 0) {
				ExternalInterface.call(LOAD_INCLUDES, headerIncludes, "head");
			}
			if (styleSheets.length > 0) {
				ExternalInterface.call(CSS_INCLUDES, styleSheets);
			}
		}
		
		private function dataLoaded(e:Event):void{
			
			var includesTotal:Number = Number(includesBefore.length + includesAfter.length);
			
			includesLeft = includesLeft - 1;
			var index:Number = Number(includesTotal) - Number(includesLeft);
			
			for (var i:int=index;i<includesTotal;i++) {
				urlLoader.load(new URLRequest(includesBefore[i]));
				break;
			}
			
			if (includesLeft <=0) {
				if (renderAtStartup) {
					callLater(render);
				}
			}
		}
		
		/**
		* Determines if HTML element should be rendered at application start up. 
		* Call render() to manually render HTML element. 
		*/
		public var renderAtStartup:Boolean = true;
		
		/** 
		* Renders the HTML element as if it was never created before. 
		*
		*/
		public function render():void {
			// fix naming issues - should always have a name and id
			// name is autopopulated by flex so if id is blank we set to name
			if (id==null) {
				//id = name;
				// if we are in a repeater, etc we need to give each instance a unique id
				id = name + String(HTMLManager.items.length + 1);
			}
	
		    // create html value object
		    // pass in this HTMLFrame instance to HTMLChild
		    // then apply only the properties an html element can support
		    // then pass it to our javascript function 
		    // that creates the html element
		    var htmlChild:HTMLElement = HTMLElement(HTMLChild.createNew(elementType, this));
		    
		    // create html element
		    var m:String = ExternalInterface.call(ADD, htmlChild);
			htmlCreated = true;
			
			htmlText = explicitHTMLText;
			
			// if this is a pop up html window then we remove it from the stage
			if (popUpChrome) {
				parent.removeChild(this);
			}
			
			dispatchEvent(new Event("htmlInitialize"));
		}
		
	    /**
		* When the html element has been created the HTMLManager runs the code in the javascript property after the 
		* htmlCreationComplete event runs and after javascriptDelay. Default is 200 milliseconds.
		*/
		[Bindable]
		public var javascriptDelay:int = 200;
		
		private var _fixTextFieldFocus:Boolean = false;
		
		/**
		* Returns focus to the application when the cursor enters a textfield
		*/
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Fix Text Field Focus", defaultValue="false")]
		public function set fixTextFieldFocus(value:Boolean):void {
			
	   		_fixTextFieldFocus = value;
	   		
			if (!htmlCreated) return;
			
	   		if (value) {
				Application.application.addEventListener(FocusEvent.FOCUS_IN, onFocusIn, false, 0, true);
				Application.application.addEventListener(MouseEvent.CLICK, onFocusIn, false, 0, true);
	   		}
	   		else {
	   			Application.application.removeEventListener(FocusEvent.FOCUS_IN, onFocusIn);
	   			Application.application.removeEventListener(MouseEvent.CLICK, onFocusIn);
	   		}
	    }
	    
	    // force the html element to lose focus
		public function forceLoseFocus():void {
			if (!htmlCreated) return;
			ExternalInterface.call(DEFOCUS, id);

		}
	    
	    // set focus to the flash swf
		public function setFocusToFlash():void {
			if (!htmlCreated) return;
			ExternalInterface.call(DEFOCUS, id);

		}
	    
		/**
		* In Internet Explorer 6 and 7 when you have the cursor in a text field in an html iframe and then place the cursor
		* into a text field in your flex application the cursor remains blinking in both text fields. When this property 
		* is enabled it will defocus the html iframe and thus stop the dual cursors when the cursor is placed in the flex text field.  
		*/
	    public function get fixTextFieldFocus():Boolean {
	    	return _fixTextFieldFocus;
	    }
	    
	    [Bindable]
	    public var isBrowserIE:Boolean = false;
	    
		// when a application gains focus we can defocus the html iframe 
		// to give the cursor back to the flex app (if the cursor is in an html text field)
		// fixTextFieldFocus must be set to true as well as this property
		// this fixes a bug between the flash player and the browser
	    [Bindable]
	    public var defocusHTMLOnApplicationClick:Boolean = true;
	    
		// when a text field or application gains focus we defocus the html iframe 
		// to give the cursor back to the flex app
		// this fixes a bug between the flash player and the browser
		private function onFocusIn(event:*):void {
			var component:*;
			
			if (isBrowserIE) {
				component = focusManager.getFocus();
				
				// defocus the html element if the cursor is in a textfield
				// we only need to do this on IE
				// is there a universal way to check??
				if (event.target is UITextField) {
					ExternalInterface.call(DEFOCUS, id);
					//UITextField(event.target).setFocus();
					focusManager.setFocus(component);
				}
				
	        	// defocus if the user clicks on the application
	        	if (event.target is Application && defocusHTMLOnApplicationClick) {
					ExternalInterface.call(DEFOCUS, Application.application.id);
	        	}
   			}
		}
		
		// this function may be deprecated due to onFocusIn() 
		// when a text field gains focus we defocus the html iframe to give the cursor back to the flex app
		// fixing a bug between the flash player and the browser
		private function checkFocus():void {
			var component:* = focusManager.getFocus();
			
			if (component is TextArea) {
				ExternalInterface.call(DEFOCUS, id);
				focusManager.setFocus(component);
			}
        	
        	// defocus if the user clicks on the application
        	if (component is Application) {
				ExternalInterface.call(DEFOCUS, Application.application.id);
				focusManager.setFocus(component);
        	}
		}
		
	    /**
		* When the html element has been created HTMLManager calls this function
		* to dispatch the htmlCreationComplete event. Still testing.
		* See htmlInitialize event as well.
		*/
		public function dispatchCreationComplete():void {
			htmlCreated = true;
			// what the heck? 
			// this evaluates the code in the javascript property after a set amount of time
			CallLater.callLater(call, javascriptDelay, [javascript]);
	    	dispatchEvent(new Event("htmlCreationComplete"));
		}
		
	    /**
		* Holds the button label that the user clicked in a HTML Alert. 
		* See HTMLManager.alert();
		*/
		public var alertButtonValue:String = "";
		
	    /**
		* Holds the labels of the buttons that the user can click in a HTML Alert. 
		* See HTMLManager.alert();
		*/
		public var popUpAlertButtons:Array = new Array(["OK"]);
		
	    /**
		* When a user clicks a button in the HTML Alert this event is dispatched. 
		* Check the alertButtonValue for the label of the button that was clicked.
		* See HTMLManager.alert();
		*/
		public function dispatchAlertHandler(buttonValue:String):void {
			alertButtonValue = buttonValue;
	    	dispatchEvent(new Event("htmlAlertHandler"));
		}
		
	    /**
		* Dispatched when the html pop up window is minimized
		*/
		public function dispatchPopUpMinimize():void {
	    	dispatchEvent(new Event(HTML_POP_UP_MINIMIZE));
		}
		
	    /**
		* Dispatched when the html pop up window is maximized
		*/
		public function dispatchPopUpMaximize():void {
	    	dispatchEvent(new Event(HTML_POP_UP_MAXIMIZE));
		}
		
	    /**
		* Dispatched when the html pop up window is restored
		*/
		public function dispatchPopUpRestore():void {
	    	dispatchEvent(new Event(HTML_POP_UP_RESTORE));
		}
		
	    /**
		* Dispatched when the html pop up window is closing
		*/
		public function dispatchPopUpClose():void {
	    	dispatchEvent(new Event(HTML_POP_UP_CLOSE));
		}
		
	    /**
		* Dispatched when the html pop up window has closed
		*/
		public function dispatchPopUpCloseComplete():void {
	    	dispatchEvent(new Event(HTML_POP_UP_CLOSE_COMPLETE));
		}
		
	    /**
		* Dispatched when the html pop up window is focused
		*/
		public function dispatchPopUpFocus():void {
	    	dispatchEvent(new Event(HTML_POP_UP_FOCUS));
		}
		
	    /**
		* Dispatched when the html pop up window is resized
		*/
		public function dispatchPopUpResize():void {
	    	dispatchEvent(new Event(HTML_POP_UP_RESIZE));
		}
		
	    /**
		* Dispatched when the html pop up window content has loaded
		*/
		public function dispatchPopUpContentLoaded():void {
	    	dispatchEvent(new Event(HTML_POP_UP_CONTENT_LOADED));
		}
		
	    /**
		* Dispatched when the html onunload event is triggered. This event is only dispatched for iframe elements.
		*/
		public function dispatchHTMLUnload():void {
	    	dispatchEvent(new Event("htmlUnload"));
		}
		
	    /**
	    * Dispatched when the user tries to go to another page. 
	    * A warning is displayed and then canceled.
		*/
		public function dispatchNavigateAwayCancel():void {
	    	dispatchEvent(new Event("navigateAwayCancel"));
		}
		
	    /**
		* When the HTML page has been loaded the HTMLManager calls this function that
		* dispatches the pageCreationComplete event. Not reliable. Not implemented. 
		* See htmlInitialize event as well.
		*/
		public function dispatchPageCreationComplete():void {
			htmlCreated = true;
			//CallLater.callLater(call, javascriptDelay, [javascript]);
	    	dispatchEvent(new Event("pageCreationComplete"));
		}
		
		// check if viewstack index is selected
		public function isSelected():Boolean {
			return _isSelected(this);
		}

		// check if viewstack index is selected
		private function _isSelected(display:Object):Boolean {
			if (display.parent == null) return true;
			if (display.parent.hasOwnProperty("selectedChild")) {
				if (display.parent.selectedChild != display) return false;
			}
			return _isSelected(display.parent);
		}

	    /**
		* Calls the javascript expression you pass to it. It can return type is dynamic.
		*/
	    public function call(value:String):* {
			if (!htmlCreated) return;
			var str:* =	ExternalInterface.call(CALL_EXPRESSION, value);
			return str;
	    }

	    /**
		* Cascades all html pop up windows
		*/
	    public function cascadeWindows():void {
			if (!htmlCreated) return;
			ExternalInterface.call(CASCADE_WINDOWS);
	    }

	    /**
		* Closes a html pop up window
		*/
	    public function closeWindow():void {
			if (!htmlCreated) return;
			ExternalInterface.call(CLOSE_WINDOW, id);
	    }

	    /**
		* Closes all html pop up windows
		*/
	    public function closeWindows():void {
			if (!htmlCreated) return;
			ExternalInterface.call(CLOSE_WINDOWS);
	    }

	    /**
		* Focuses in on a html pop up window
		*/
	    public function focusWindow():void {
			if (!htmlCreated) return;
			ExternalInterface.call(FOCUS_WINDOW, id);
	    }

	    /**
		* Maximizes a html pop up window
		*/
	    public function maximizeWindow():void {
			if (!htmlCreated) return;
			ExternalInterface.call(MAXIMIZE_WINDOW, id);
	    }

	    /**
		* Maximizes all html pop up windows
		*/
	    public function maximizeWindows():void {
			if (!htmlCreated) return;
			ExternalInterface.call(MAXIMIZE_WINDOWS);
	    }

	    /**
		* Minimizes a html pop up window
		*/
	    public function minimizeWindow():void {
			if (!htmlCreated) return;
			ExternalInterface.call(MINIMIZE_WINDOW, id);
	    }

	    /**
		* Minimizes all html pop up windows
		*/
	    public function minimizeWindows():void {
			if (!htmlCreated) return;
			ExternalInterface.call(MINIMIZE_WINDOWS);
	    }

	    /**
		* Restores a minimized html pop up window
		*/
	    public function restoreMinimizedWindow():void {
			if (!htmlCreated) return;
			ExternalInterface.call(RESTORE_MINIMIZED_WINDOW, id);
	    }

	    /**
		* Restores a html pop up window
		*/
	    public function restoreWindow():void {
			if (!htmlCreated) return;
			ExternalInterface.call(RESTORE_WINDOW, id);
	    }

	    /**
		* Hides or shows a html pop up window dock
		*/
	    public function toggleWindowDock():void {
			ExternalInterface.call(TOGGLE_WINDOW_DOCK);
	    }
	    
	    private var _windowDockVisibility:Boolean = false;
	    public function get windowDockVisibility():Boolean {
			return _windowDockVisibility;
	    }

	    /**
		* Sets the visibility of the pop up window dock
		*/
	    public function set windowDockVisibility(value:Boolean):void {
	    	_windowDockVisibility = value;
			ExternalInterface.call(SET_WINDOW_DOCK_VISIBILITY, value);
	    }

	    /**
		* Sets the visibility of the pop up window dock
		*/
	    public function setWindowDockVisibility(value:Boolean):void {
			ExternalInterface.call(SET_WINDOW_DOCK_VISIBILITY, value);
	    }
		
		private var _popUpLaunchCentered:Boolean = false;
		public function get popUpLaunchCentered():Boolean {
			return _popUpLaunchCentered;
		}
		
		/**
		* When launching a pop up window with HTML chrome disregard the x and y and center it on the screen.
		* Only applys when creating a new window. 
		*/
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Center Pop Up HTML Window", defaultValue="false")]
		public function set popUpLaunchCentered(value:Boolean):void {
			_popUpLaunchCentered = value;
		}
		
		private var _relativeMovie:Boolean = false;
		public function get relativeMovie():Boolean {
			return _relativeMovie;
		}
		
		/**
		* When the flex application is not in the upper left hand corner of the browser then you need to enable this
		* for the movie to be positioned correctly. Do not enable this willy nilly. It could possibly be costly in pentiums if you move the 
		* HTML around.
		*/
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Relative Positioned Movie", defaultValue="false")]
		public function set relativeMovie(value:Boolean):void {
			_relativeMovie = value;
			ExternalInterface.call(RELATIVE_MOVIE, value);
		}
		
		/**
		* Adds drag behavior to a HTML pop up window
		*/
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Pop Up Draggable", defaultValue="true")]
		public function set popUpDraggable(value:Boolean):void {
			_popUpDraggable = value;
		}
		
		private var _popUpDraggable:Boolean = true;
		public function get popUpDraggable():Boolean {
			return _popUpDraggable;
		}
		
		/**
		* Adds resize behavior to a HTML pop up window
		*/
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Pop Up Resizable", defaultValue="true")]
		public function set popUpResizable(value:Boolean):void {
			_popUpResizable = value;
		}
		
		private var _popUpResizable:Boolean = true;
		public function get popUpResizable():Boolean {
			return _popUpResizable;
		}
		
		/**
		*  Adds a close button to HTML pop up windows
		*/
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Pop Up Closeable", defaultValue="true")]
		public function set popUpCloseable(value:Boolean):void {
			_popUpCloseable = value;
		}
		
		private var _popUpCloseable:Boolean = true;
		public function get popUpCloseable():Boolean {
			return _popUpCloseable;
		}
		
		/**
		* Adds a minimize button to HTML pop up windows
		*/
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Pop Up Minimizable", defaultValue="false")]
		public function set popUpMinimizable(value:Boolean):void {
			_popUpMinimizable = value;
		}
		
		private var _popUpMinimizable:Boolean = false;
		public function get popUpMinimizable():Boolean {
			return _popUpMinimizable;
		}
		
		/**
		* Adds a maximize button to HTML pop up windows
		*/
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Pop Up Maximizable", defaultValue="false")]
		public function set popUpMaximizable(value:Boolean):void {
			_popUpMaximizable = value;
		}
		
		private var _popUpMaximizable:Boolean = false;
		public function get popUpMaximizable():Boolean {
			return _popUpMaximizable;
		}
		
		/**
		* Prompt the user with a javascript alert if they try to navigate away from the page
		*/
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Prompt User when Unloading", defaultValue="false")]
		public function set promptOnUnload(value:Boolean):void {
			htmlManager.promptOnUnload = value;
			ExternalInterface.call(PROMPT_ON_UNLOAD, value, htmlManager.promptOnUnloadMessage);
		}
		
		public function get promptOnUnload():Boolean {
			return htmlManager.promptOnUnload;
		}
		
		/**
		* Message in prompt to the user with a javascript alert if they try to navigate away from the page
		 * This message is shown in between the default message the browsers displays.
		 * "Are you sure you want to navigate away from this page? Press OK to continue, or Cancel to stay on the current page."
		*/
		[Bindable]
	    [Inspectable(type="String", category="General", name="Prompt User when Unloading Message")]
		public function set promptOnUnloadMessage(value:String):void {
			htmlManager.promptOnUnloadMessage = value;
			ExternalInterface.call(PROMPT_ON_UNLOAD, value, htmlManager.promptOnUnloadMessage);
		}
		
		public function get promptOnUnloadMessage():String {
			return htmlManager.promptOnUnloadMessage;
		}

		private var _clearHTMLText:Boolean = true;
		
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Clear HTML Text", defaultValue="true")]
		public function set clearHTMLText(value:Boolean):void {
			
	   		_clearHTMLText = value;
	   		if (value) {
				htmlText = "";
	   		}
	    }
	    
		/**
		* Clear html text value. When we show the html component, first the flex uicomponent is shown
	    * and then the html element is shown. Because it is not instantaneous we see the flex uicomponent briefly 
	    * before the html element overlays it. Any contents in the uicomponent is shown. 
	    * When enabled this value clears it and therefore clears the flicker
		*/
	    public function get clearHTMLText():Boolean {
	    	
	    	return _clearHTMLText;
	    }
	    
		private var _fitToContentHeight:Boolean = false;
		
		/**
	    * Fits the component to the height of the HTML content. The value returned by the browser is not always accurate. 
	    * Sometimes it is one or two pixels too short. You can use the fitToHeightOffset property to compensate for this.
	    * <br/>Note: This does not support pages that are <b>not</b> on your site. This is a security in place set by the browser.
	    * When the browser is not able to return the height it returns -1 and a heightFault event is dispatched. 
	    */
	    public function get fitToContentHeight():Boolean {
	    	
	    	return _fitToContentHeight;
	    }
	    
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Fit to Content Height", defaultValue="false")]
		public function set fitToContentHeight(value:Boolean):void {
	    	
	   		_fitToContentHeight = value;
	   		
	   		// check if user wants to fit component to height of content
			if (!_fitToContentHeight) {
			
			    // creates a new timer
		        if (getHeightTimer!=null) {
		        	// clear the Timer
		        	getHeightTimer.stop();
		        	getHeightTimer.reset();
		        }
				return;
			}
			
			var repeatCount:int = Math.ceil(getHeightTimeout/getHeightInterval);
			
	        // creates a new timer
	        if (getHeightTimer==null) {
	        	// creates a new Timer
	        	getHeightTimer = new Timer(getHeightInterval,repeatCount);
	        }
	        
			getHeightTimer.delay = getHeightInterval;
	        getHeightTimer.repeatCount = repeatCount;
	        
	        if (getHeightTimer.running) getHeightTimer.reset();
	        getHeightTimer.start();
	        fitToElementHeight();
	
	    }private var _padding:String = "0px";
		
		/**
	    * Sets the html padding of the html component. Values must include the "px" such as "10px 12px" 
	    */
	    public function get padding():String {
	    	return _padding;
	    }
	    
		[Bindable]
	    [Inspectable(type="String", category="General", name="Set Padding", defaultValue="0px")]
		public function set padding(value:String):void {
	   		_padding = value;
	    }

		/**
		* When the fitToContentHeight is true a timer is run that checks the height of the HTML element.
		* You can set the time between each call with this property. Default is 500 (milliseconds). 
		* You could put this to 20ms if you wanted but test it out on your target audience. 
		 * You'll also want to adjust the getHeightTimeout value so that it isn't running the full 5 seconds
		 * unless that is what you are after. 
		*/
		[Bindable]
	    [Inspectable(type="int", category="General", name="Fit To Height Interval", defaultValue="500")]
		public var getHeightInterval:int = 500;
		
		// we should set a property in javascript when the page completes loading - haven't done this
		// i dont think we can set a property for when html text is loaded in a division
		
		/**
		* When the fitToContentHeight is true a timer is run that checks the height of the HTML element.
		* This defines the duration we continue to check the HTML element height. The default is 5 seconds (5000 milliseconds).
		*/
		public var getHeightTimeout:int = 5000;
		
		/**
		* When the fitToContentHeight is true a timer is run that checks the height of the HTML element. 
		* This continues for the length defined in the getHeightTimeout property. Default is 5000 milliseconds.
		*/
		public var getHeightTimer:Timer;
	
		/**
		* When the fitToContentHeight is true a timer is run that checks the height of the HTML element.
		* This method is called at the timer interval.
		*/
	    protected function onGetHeightTick(evt:TimerEvent):void {
			if (!htmlCreated) return;
			
			fitToElementHeight();
	    }
	    
	    /**
	    * Gets the raw height of the HTML element. Does not include borders, padding etc. 
		*/
	    public function getElementHeight():int {
			if (!htmlCreated) return -1;
	    	var value:int = parseInt(ExternalInterface.call(GET_HEIGHT, id));
	    	return value;
	    }
	    
	    /**
	    * When the fitToContentHeight is true a timer is run that checks the height of the HTML element.
	    * This method is called and if the height is different then the current height the component is resized. 
	    * Note: This does not get the height of pages not on your domain. It will return -1 and dispatch a heightFault event.
		*/
	    public function fitToElementHeight():int {
			if (!htmlCreated) return -1;
	    	var elementHeight:int = ExternalInterface.call(GET_HEIGHT, id);
	    	var borderOffset:int = (height - contentHeight);
	    	var adjustedElementHeight:int = elementHeight + borderOffset + fitToHeightOffset;
	    	var newHeight:int = 0;
	    	
	    	if (elementHeight==-1) {
	    		dispatchEvent(new Event("heightFault"));
	    		return -1;
	    	}
			
	    	if (adjustedElementHeight == height || elementHeight == 0 || adjustedElementHeight-1 == height ) {
				//getHeightTimer.stop();
			}
			else {
				newHeight = adjustedElementHeight;
				height = newHeight;
			}
			
			return height;
	    }
	    
	    /**
	    * When the fitToContentHeight is true a timer is run that checks the height of the HTML element.
	    * Sometimes the height the browser returns is a pixel or two less than the actual height.
	    * This property lets you adjust or offset the height. 
		*/
	    [Bindable]
	    [Inspectable(type="Number", category="General", name="Fit To Height Offset", defaultValue="0")]
	    public var fitToHeightOffset:int = 0;
	    
	    /**
		* When the fitToContentHeight is true a timer is run that checks the height of the HTML element.
		* When the timer has finished this handler is called. 
		*/
	    protected function onGetHeightComplete(evt:TimerEvent):void {
	    	dispatchEvent(new Event("fitToContentHeightComplete"));
	    }
		
		/**
		* This method allows you to set the Document Window Title
		*/
		public function setDocumentTitle(value:String):void {
			if (!htmlCreated) return;
		    ExternalInterface.call(SET_DOCUMENT_TITLE, value);
		}
		
		/**
		* When a browser does not support ExternalInterface, which is the api that talks to JavaScript, 
		* it passes a false value to this function. A user can define their own external interface function.
		*/
	    public function defaultExternalInterfaceFunction(value:Boolean):Boolean {
	        return value;
	    }
	
		// User defined function to let user enable or disable creation of html element
		private var _externalInterfaceFunction:Function = defaultExternalInterfaceFunction;
	
		/**
		* When a browser does not support ExternalInterface, which is the api that talks to JavaScript, 
		* it passes a false value to the externalInterfaceFunction function. You can define your own external interface function.
		* If the value passed to this function is false then ExternalInterface is not supported. 
		*/
		public function set externalInterfaceFunction(value:Function):void {
	    	
	    	if (value!=null) {
	    		_externalInterfaceFunction = value;
	    	}
	    }
	    
	    /**
		* When a browser does not support ExternalInterface, which is the api that talks to JavaScript, 
		* it passes a false value to the externalInterfaceFunction function. You can define your own external interface function.
		* If the value passed to this function is false then ExternalInterface is not supported. 
		*/
	    public function get externalInterfaceFunction():Function {
	    	
	    	return _externalInterfaceFunction;
	    }
		
		/**
		* We create a public method that javascript can call
		*/
		protected function addHTMLCallBacks():void {
			// we create a public method that javascript can call
			// from javascript we pass in the id of the html control and dispatch the event to the correct control
			// we should do a check here to only run this once 
			if (htmlManager.addedCallbacks==false) {
			    ExternalInterface.addCallback("htmlAlertHandler", HTMLManager.onHTMLAlertHandler);
			    ExternalInterface.addCallback("htmlCreationComplete", HTMLManager.onHTMLCreationComplete);
				// html pop up window events 
			    ExternalInterface.addCallback("htmlPopUpMinimize", HTMLManager.onHTMLPopUpMinimize);
			    ExternalInterface.addCallback("htmlPopUpMaximize", HTMLManager.onHTMLPopUpMaximize);
			    ExternalInterface.addCallback("htmlPopUpRestore", HTMLManager.onHTMLPopUpRestore);
			    ExternalInterface.addCallback("htmlPopUpClose", HTMLManager.onHTMLPopUpClose);
			    ExternalInterface.addCallback("htmlPopUpCloseComplete", HTMLManager.onHTMLPopUpCloseComplete);
			    ExternalInterface.addCallback("htmlPopUpContentLoaded", HTMLManager.onHTMLPopUpContentLoaded);
			    ExternalInterface.addCallback("htmlPopUpFocus", HTMLManager.onHTMLPopUpFocus);
			    ExternalInterface.addCallback("htmlPopUpResize", HTMLManager.onHTMLPopUpResize);
			    // add callback if user tries to navigate away from frame but cancels
			    ExternalInterface.addCallback("onNavigateAwayCancel", HTMLManager.onNavigateAwayCancel);
			    ExternalInterface.addCallback("htmlUnload", HTMLManager.onHTMLUnload);
			    // unreliable
			    ExternalInterface.addCallback("onLoadComplete", HTMLManager.onPageCreationComplete);
			    htmlManager.addedCallbacks = true;
		 	}
		}
		
	    /**
		 *  If the component is inside of a pop up we set this value to true. Default is false. 
	     */
		public var insidePopUp:Boolean = false;
		
	    /**
		 *  The last value of htmlText that was set.
		 *  We have to keep track of this because when you set the htmlText
		 *  of a TextField and read it back, you don't get what you set.
		 *  In general it will have additional HTML markup corresponding
		 *  to the defaultTextFormat set from the CSS styles.
		 *  If this var is null, it means that 'text' rather than 'htmlText'
		 *  was last set.
	     */
	    public function get explicitHTMLText():String {
	    	
	    	return _explicitHTMLText;
	    }
	
	    /**
	     *  @private
		 *  The last value of htmlText that was set.
		 *  We have to keep track of this because when you set the htmlText
		 *  of a TextField and read it back, you don't get what you set.
		 *  In general it will have additional HTML markup corresponding
		 *  to the defaultTextFormat set from the CSS styles.
		 *  If this var is null, it means that 'text' rather than 'htmlText'
		 *  was last set.
		 *	Textarea saves this value to explicitHTMLText. We save it to _explicitHTMLText.
	     */
	    private var _explicitHTMLText:String = null; 
		
		/**
		* Used to define the load method of the pop up method. iframe, html or xhr
		*/
		public var popUpLoadMethod:String = "html";
		
		
		/**
		* Used to flag the pop up as an alert
		*/
		public var popUpAlert:Boolean = false;
		
		private var _popUpHTML:String = "";
		
		/**
		* Can be used to set the HTML value of a pop up window. 
		 * Same as setting htmlText.
		*/
		[Bindable]
	    [Inspectable(type="String", category="General", name="Pop Up HTML")]
		public function set popUpHTML(value:String):void {
			if (!htmlCreated) return;
	   		htmlText = value;
	    }
		
	    public function get popUpHTML():String {
	    	return _popUpHTML;
	    }
	    
		/**
		* Used to set modal option of HTML pop up
		*/
	    public function get popUpModal():Boolean {	
	    	return _popUpModal;
	    }
	    
		private var _popUpModal:Boolean = false;
		
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Pop Up Modal", defaultValue="false")]
		public function set popUpModal(value:Boolean):void {
	   		_popUpModal = value;
	    }
	    
		/**
		* Used to set the header height in a HTML pop up
		*/
	    public function get popUpHeaderHeight():Number {	
	    	return _popUpHeaderHeight;
	    }
	    
		private var _popUpHeaderHeight:Number = 32;
		
		[Bindable]
	    [Inspectable(type="Number", category="General", name="Pop Up Header Height", defaultValue="32")]
		public function set popUpHeaderHeight(value:Number):void {
	   		_popUpHeaderHeight = value;
	    }
	    
		/**
		* Used to set the footer height in a HTML pop up
		*/
	    public function get popUpFooterHeight():Number {	
	    	return _popUpFooterHeight;
	    }
	    
		private var _popUpFooterHeight:Number = 16;
		
		[Bindable]
	    [Inspectable(type="Number", category="General", name="Pop Up Footer Height", defaultValue="16")]
		public function set popUpFooterHeight(value:Number):void {
	   		_popUpFooterHeight = value;
	    }
	    
		/**
		* Used to set the top position in the header title text in a HTML pop up
		*/
	    public function get popUpTitleTop():Number {	
	    	return _popUpTitleTop;
	    }
	    
		private var _popUpTitleTop:Number = 10;
		
		[Bindable]
	    [Inspectable(type="Number", category="General", name="Pop Up Header Title Top Position", defaultValue="10")]
		public function set popUpTitleTop(value:Number):void {
	   		_popUpTitleTop = value;
	    }
	    
		/**
		* Used to set the top position in the header control buttons in a HTML pop up
		*/
	    public function get popUpControlsTop():Number {	
	    	return _popUpControlsTop;
	    }
	    
		private var _popUpControlsTop:Number = 10;
		
		[Bindable]
	    [Inspectable(type="Number", category="General", name="Pop Up Header Controls Top Position", defaultValue="10")]
		public function set popUpControlsTop(value:Number):void {
	   		_popUpControlsTop = value;
	    }
	    
		/**
		* Use to show a pop up with HTML border.
		*/
	    public function get popUpChrome():Boolean {
	    	return _popUpChrome;
	    }
	    
		private var _popUpChrome:Boolean = false;
		
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Pop Up Chrome", defaultValue="false")]
		public function set popUpChrome(value:Boolean):void {
	   		_popUpChrome = value;
	    }
	    
		/**
		* Use to set the title text of the HTML pop up window.
		*/
	    public function get popUpTitle():String {
	    	return _popUpTitle;
	    }
		
		private var _popUpTitle:String = "";
		
		[Bindable]
	    [Inspectable(type="String", category="General", name="Pop Up Title", defaultValue="")]
		public function set popUpTitle(value:String):void {
	   		_popUpTitle = value;
	    }
		
		/**
		* Gets the HTML from the HTML element in the browser. If its an div then it gets the innerHTML. 
		* If its an editor it gets the HTML source code.
		* Does not get any value if element is an iframe.
		*/
		public function getHTML():String {
			if (!htmlCreated) return null;
			return ExternalInterface.call(GET_HTML_TEXT, id, elementType, editorType, popUpChrome);
		}
		
		/**
		* Sets the HTML of the HTML element in the browser. Same as setting component.htmlText = "html content";
		* Does not work with iframe
		*/
		public function setHTML(value:String):void {
			if (!htmlCreated) return;
			htmlText = value;
		}
		
	    /**
	    * If the element is a division this property returns the innerHTML of the division element. 
	    * If the element is an editor then this property returns the HTML in the editor. 
		*/
	    override public function get htmlText():String {
	    	
			// changed functionality in version 4 to return html content
	    	//if (_clearHTMLText) {
	        //	return explicitHTMLText;
	        //}
	        
			return ExternalInterface.call(GET_HTML_TEXT, id, elementType, editorType, popUpChrome);
	    	//return super.htmlText;
	    }
		
	
	    [Bindable("htmlTextChanged")]
	    [CollapseWhiteSpace]
	    [Inspectable(category="General", defaultValue="")]
	    [NonCommittingChangeEvent("change")]
	    
		/**
		* This property is used to set the HTML text.
		* When using an editor the HTML text defined here is displayed in the editor.
		* Wrap this value in CDATA tags. Does nothing is element is an iframe. 
		*/
		override public function set htmlText(value:String):void {
	        
	        // The htmlText property can't be set to null, only to an empty string
			if (!value) {
				value = "";
			}
			
			_explicitHTMLText = value;
			super.htmlText = value;
			
			if (!htmlCreated) return;
			
			// get rid of flicker effect when hiding or showing html 
	        if (_clearHTMLText) {
	        	super.htmlText = "";
	        }
			
			ExternalInterface.call(SET_HTML_TEXT, id, value, elementType, editorType, popUpChrome);
			dispatchEvent(new Event("htmlTextChanged"));
			
			// check if user wants to fit component to height of content
			if (!fitToContentHeight) return;
			
			var repeatCount:int = Math.ceil(getHeightTimeout/getHeightInterval);
			getHeightTimer.delay = getHeightInterval
	        getHeightTimer.repeatCount = repeatCount;
	        
	        if (getHeightTimer.running) getHeightTimer.reset();
	        getHeightTimer.start();
	        fitToElementHeight();
	        
	    }
	    
	    private var _backgroundTransparent:Boolean = false;
	    
	    /**
	    * Setting this sets the backgroundColor to null in the HTML element NOT the TextArea behind it
	    * You will still see the backgroundColor of the TextArea.
	    * To set the TextArea background color opacity set the backgroundAlpha to a value between 0 to 1
	    * Also set the clearHTMLText property to true to clear any text out of the TextArea  
		*/
		public function set backgroundTransparent(value:Boolean):void {
			_backgroundTransparent = value;
		}
	    public function get backgroundTransparent():Boolean {
	    	return _backgroundTransparent;
	    }
	    
	    private var _includesBefore:Array = [];
	    private var _includesAfter:Array = [];
	    private var _headerIncludes:Array = [];
	    
	    /**
	    * This is an array of stylesheets to load dynamically
		*/
	    public function get styleSheets():Array {
	    	return _styleSheets;
	    }
	    
	    private var _styleSheets:Array = [];
	    
		public function set styleSheets(value:Array):void {
			_styleSheets = value;
		}
	    
	    /**
	    * This is an array of javascript include files to load dynamically into the html head section. 
	    * You can also use the includesBefore to load js files into the body before and after the element is added to the page 
		*/
	    public function get headerIncludes():Array {
	    	return _headerIncludes;
	    }

		public function set headerIncludes(value:Array):void {
			_headerIncludes = value;
		}
	    
	    /**
	    * This is an array of javascript include files to load dynamically. 
	    * Unexpected results or scope issues can occur when loading js files from other domains since this is added to the BODY tag.
	    * You can also use the headerIncludes to load js files into the html head 
		*/
	    public function get includesBefore():Array {
	    	return _includesBefore;
	    }

		public function set includesBefore(value:Array):void {
			_includesBefore = value;
		}
	    
	    /**
	    * This is an array of javascript include files to load dynamically. This is loaded directly after the division is added to the HTML DOM.
	    * Unexpected results or scope issues can occur when loading js files from other domains since this is added to the BODY tag.
	    * You can also use the headerIncludes to load js files into the html head  
		*/
	    public function get includesAfter():Array{
	    	
	    	return _includesAfter;
	    }

		public function set includesAfter(value:Array):void {
			_includesAfter = value;
		}
	    
	    /**
	    * This property gets the explicit value of the JavaScript stored in the component.
		*/
	    public function get javascript():String {
	    	return _javascript;
	    }
		
	    private var _javascript:String = "";
		
		/**
		* This property is used to call JavaScript.
		* The JavaScript defined here is rendered after the element has been created.
		* Wrap this value in CDATA tags. Example:
		<mx:String id="javascript2">
		< ![CDATA[ myJavaScriptFunction() ] ] >
		< /mx:String>
		<ns1:HTML elementType="division" javascript="{javascript2}">
		*/
		public function set javascript(value:String):void {
	        
	        // This property can't be set to null, only to an empty string
			if (!value) {
				value = "";
			}
			
			_javascript = value;
			
			if (!htmlCreated) return;
	        
	    }
		
		/**
		* The specific rich text editor to use when the elementType is set to editor. Default value is "fckeditor". 
		* To add a different editor define it here and then update the addChildEditor function in the JavaScript. 
		* See editor website for more information.
		*/
		[Bindable]
	    [Inspectable(type="String", category="General", name="Editor Type", defaultValue="fckeditor")]
		public var editorType:String = "fckeditor";
		
		/**
		* Path to the editor directory. Default value is "fckeditor/". See editor website.
		*/
		[Bindable]
	    [Inspectable(type="String", category="General", name="Editor Base Path", defaultValue="fckeditor/")]
		public var editorPath:String = "fckeditor/";
		
		/**
		* Path to the editor config file. Default value is "". Used for FCKEditor. See editor website.
		*/
		[Bindable]
	    [Inspectable(type="String", category="General", name="Editor Config Path", defaultValue="")]
		public var configPath:String = "";
		
		/**
		* Options specific to the editor you are using. 
		*/
		[Bindable]
	    [Inspectable(type="*", category="General", name="Editor Config Options")]
		public var editorOptions:* = "";
		
		/**
		* Options specific to the pop up you are using.
		*/
		[Bindable]
	    [Inspectable(type="*", category="General", name="Pop Up Options")]
		public var popUpOptions:* = "";
		
		/**
		* Can be iframe, division or editor. In iframe mode you set the source property to a URL. If you load a local html page then
		* you will not see any visible indication if you view it in Internet Explorer. In division mode you enter HTML markup in the 
		* htmlText property. Be sure to wrap the content in CDATA blocks. In editor mode you can specify the config path and the editor path.
		* See quickstart guide for instructions for the editor.
		* <br/>Note: You can pass Javascript include files through this property. Place your JavaScript includes on the wrapper page.
		*/
		[Bindable]
	    [Inspectable(type="String", enumeration="iframe,division,editor", category="General", name="HTML Element", defaultValue="iframe")]
		public var elementType:String = IFRAME;
		
		/**
		* Option to set the clip rectangle of the div container.
		*/
		public function get clip():String {
			return _clip;
		}
		
		private var _clip:String = "";
		
		/**
		* Option to set the clip rectangle of the div container. Not supported
		*/
		[Bindable("htmlClipChanged")]
	    [Inspectable(type="String", category="General", name="HTML Clip")]
		public function set clip(value:String):void {
			_clip = value;
			
			if (!htmlCreated) return;
			
			ExternalInterface.call(SET_CLIP, id, value);
			dispatchEvent(new Event("htmlClipChanged"));
		}

		/**
		* Option to set the scroll policy of the div container. 
		* Not for use with iframes only div's. Not supported.
		*/
		[Bindable("htmlScrollPolicyChanged")]
	    [Inspectable(type="String", category="General", name="HTML Scroll Policy", 
	    enumeration="auto,off,on,overflow,resize,scroll,none", defaultValue="auto")]
		public function set htmlScrollPolicy(value:String):void {
			_htmlScrollPolicy = value;
			
			if (!htmlCreated) return;
			if (elementType == IFRAME) return;
			
			ExternalInterface.call(HTML_SCROLL_POLICY, id, value);
			dispatchEvent(new Event("htmlScrollPolicyChanged"));
		}
		
		/**
		* Option to set the scroll policy of the div container. 
		* Does not work for iframe or really anything but IE. You may never use this.
		*/
		public function get htmlScrollPolicy():String {
			return _htmlScrollPolicy;
		}
		
		private var _htmlScrollPolicy:String = "auto";
		
		/**
		* Allow user the ability to hide the html element but still show the Flex UIComponent (TextArea) behind it. You shouldn't use this. 
		* except in odd cases. Use component.visible property or use component.setVisibility method.
		* We must resize it to 0px high to get around firefox issue (flash right click context menus in the wrong place if you only hide it)
		 * */
		[Bindable("htmlVisibilityChanged")]
	    [Inspectable(type="Boolean", category="General", name="HTML Visibility", defaultValue="true")]
		public function set htmlVisibility(value:Boolean):void {
			_htmlVisibility = value;
			
			if (!htmlCreated) return;
			
			var functionName:String = (value) ? SHOW : HIDE;
			var left:int = (value) ? contentLeft : offscreenOffset;
			
			// component visibility has priority
			if (visible) {
				// add parameter to move html element offscreen (functionname, id, moveOffscreen)
				ExternalInterface.call(functionName, id, hideOffscreen, left, contentWidth, contentHeight);
				dispatchEvent(new Event("htmlVisibilityChanged"));
			}
		}
		
		/**
		* Allow user the ability to hide the html element but still show the Flex UIComponent (TextArea) behind it. You shouldn't use this. 
		* except in odd cases. Use component.visible property or use component.setVisibile method.
		* We must resize it to 0px high to get around firefox issue (flash right click context menus in the wrong place if you only hide it)
		*/
		public function get htmlVisibility():Boolean {
			return _htmlVisibility;
		}
	
		/**
		* Allow user the ability to show or hide the component manually. This method is available because the event handling framework has two stages. 
		* If your component code is run on the first event stage then there are times when you may want to manually hide or show the html component. 
		* You may never need to use this. You may need to use this for pop up windows.
		*/
		[Bindable("visibilityChanged")]
		public function setVisibility(value:Boolean):void {
			
			if (!htmlCreated) return;
			super.visible = value;
			
			var functionName:String = (value) ? SHOW : HIDE;
			var left:int = (value) ? contentLeft : offscreenOffset;
			
			// add parameter to move html element offscreen (functionname, id, moveOffscreen)
			ExternalInterface.call(functionName, id, hideOffscreen, left, contentWidth, contentHeight);
			dispatchEvent(new Event("visibilityChanged"));
		}
		
		/**
		* Remove the HTML element completely. Used when HTML component is in a pop up window. 
		* Had some trouble with this since it was called when the Application was resized. So you must use 
		* component.visible = false or component.removeElement(). 
		*/
		protected function removeHandler(event:Event):void {
			
			if (!htmlCreated) return;
			// we should remove the html component when it is in a pop up but 
			// when the application resizes this event is called??? 
			//ExternalInterface.call(REMOVE, id);
			if (insidePopUp) {
				
				if(removeElementOnRemove) {
					
					removeElement();
				}
				else {
					visible = false;
				}
			}
		}
		
		/**
		* When the html element is in a popup we can completely remove the html element on the remove event
		 * otherwise we hide it. 
		* Default is to remove element (true). If its false then we hide the element.
		* component.visible = false or component.removeElement(). 
		*/
		public var removeElementOnRemove:Boolean = true;
		
		/**
		* Remove the HTML element completely.
		*/
		public function removeElement(removeFromStage:Boolean = true):void {
			if (!htmlCreated) return;
			ExternalInterface.call(REMOVE, id);
			if (removeFromStage && this.parent!=null) {
				this.parent.removeChild(this);
			}
			removeListeners();
			HTMLManager.removeFromItems(this);
			dispatchEvent(new Event("removeElement"));
			// should we call this=null here??? contact me
		}
		
		/**
		* Get a property from HTML. Wrapper for ExternalInterface call. There two methods to use this. 
		* Usage 1 - var returnValue:* = htmlComponent.getPropertyValue("elementId", "innerHTML");
		* Usage 2 - var returnValue:* = htmlComponent.getPropertyValue("document.href.location");
		* Usage 3 - var returnValue:* = htmlComponent.call(javascriptCode);
		*/
		public function getPropertyValue (elementId:String, elementProperty:String=""):* {
			if (!htmlCreated) return null;
			return ExternalInterface.call(GET_PROPERTY_VALUE, elementId, elementProperty);
		}
		
		private var _htmlVisibility:Boolean = true;
		
		/**
		* Option to hide element offscreen to get around firefox issue (left and right clicking positioning issues). 
		 * Deprecated. Using different method so this is not even used.  
		*/
		[Bindable]
	    [Inspectable(type="Boolean", category="General", name="Hide Offscreen", defaultValue="true")]
		public var hideOffscreen:Boolean = true;
		
		/**
		* Option to hide element offscreen to get around firefox issue (clicking stops working issues). 
		 * Deprecated. Using different method so this is not even used. 
		*/
		[Bindable]
	    [Inspectable(type="int", category="General", name="Offscreen Offset", defaultValue="-5000")]
		public var offscreenOffset:int = -5000;
		
		/**
		* Show the HTML element.
		*/
		protected function showHandler(event:*):void {
			
			if (!htmlCreated || popUpChrome==true) { 
				return;
			}
			
			// cannot show if htmlVisibility is set to false
			// allows dudes the ability to hide the html 
			// but still show the component
			if (htmlVisibility) {
				ExternalInterface.call(SHOW, id, hideOffscreen, contentLeft, contentWidth, contentHeight);
			}
		}
		
		/**
		* Hide the HTML element.
		*/
		protected function hideHandler(event:*):void {
			
			if (!htmlCreated || popUpChrome==true) { 
				return;
			}
			
			ExternalInterface.call(HIDE, id, hideOffscreen, offscreenOffset);
		}
		
		/**
		* Set the visibility of the HTML element based on visibility of parent components
		*/
		protected function htmlVisibleHandler(event:Event):void {
			
			if (!htmlCreated || popUpChrome==true) { 
				return;
			}
			
			// always hide the component if asked for
			if (event.type == FlexEvent.HIDE) {
				ExternalInterface.call(HIDE, id, hideOffscreen, offscreenOffset);
				return;
			}
					
			var currentParent:DisplayObjectContainer = this.parent;
			
			// climb up the chain of containers and see if a parent is visible
			while (currentParent != null) {
				
				if (currentParent.visible == false) {	
					ExternalInterface.call(HIDE, id, hideOffscreen, offscreenOffset);
					return;
				}
				
				currentParent = currentParent.parent;
			}
			
			// if the values haven't changed (use javascript function) then do nothing
			if (contentWidth<0) {
				callLater(showLater);
			}
			else {
				ExternalInterface.call(SHOW, id, hideOffscreen, contentLeft, contentWidth, contentHeight);
			}
		}
		
		public function showLater():void {
			ExternalInterface.call(SHOW, id, hideOffscreen, contentLeft, contentWidth, contentHeight);
		}
		
		public function hideLater():void {
			ExternalInterface.call(HIDE, id, hideOffscreen, offscreenOffset);
		}
		
		/**
		* Resize HTML element. 
		*/
		protected function htmlResizeHandler(event:ResizeEvent):void {
			
			if (!htmlCreated || popUpChrome==true) { 
				return;
			}
			
			if (width != event.oldWidth && height != event.oldHeight) {
				ExternalInterface.call(SIZE, id, contentWidth, contentHeight);
			}
			else if (width != event.oldWidth) {
				ExternalInterface.call(SIZE, id, contentWidth, null);
			}
			else if (height != event.oldHeight) { 
				ExternalInterface.call(SIZE, id, null, contentHeight);
			}
		}
		
		/**
		* Reposition when the Application is resized.
		*/
		protected function applicationResize(event:Event):void {
			// the contentTop and contentLeft are not accurate until a frame (or more?) after 
			// the application update complete event
			// UPDATE - we may need to listen in the bubble event phase (second phase)
			callLater(repositionHandler);
		}
		
		/**
		* Reposition and resize HTML element when Application is resized
		*/
		protected function repositionHandler():void {
			
			if (!htmlCreated || popUpChrome==true) { 
				return;
			}
			ExternalInterface.call(MOVE, id, contentLeft, contentTop);
			ExternalInterface.call(SIZE, id, contentWidth, contentHeight);
		}
		
		/**
		* Refresh HTML element. Resize, reposition. If the first arguement is true then render the component. Render will create the component.
		* If the component has already been created then we create it again over writing the first element.  
		*/
		public function refreshElement(rerender:Boolean = false):void {
			
			if (!htmlCreated) return;
			if (rerender) {
				render();
				return;
			}
			ExternalInterface.call(MOVE, id, contentLeft, contentTop);
			ExternalInterface.call(SIZE, id, contentWidth, contentHeight);
		}
		
		/**
		* Sets the position and size of the HTML element. This can be over written if the container moves.
		*/
		public function setPosition(left:Number = 0, top:Number = 0, width:Number = 0, height:Number = 0):void {
			
			if (!htmlCreated) return;
			ExternalInterface.call(MOVE, id, left, top);
			ExternalInterface.call(SIZE, id, width, height);
		}
		
		/**
		* Move HTML element.
		*/
		protected function htmlMoveHandler(event:MoveEvent):void {
			
			if (!htmlCreated || popUpChrome==true) { 
				return;
			}
			
			if (x != event.oldX && y != event.oldY) {
				ExternalInterface.call(MOVE, id, contentLeft, contentTop);
			}
			else if (x != event.oldX) {
				ExternalInterface.call(MOVE, id, contentLeft, null);
			}
			else if (y != event.oldY) {
				ExternalInterface.call(MOVE, id, null, contentTop);
			}
		}
		
		/**
		* Reposition HTML element on scrollbar events
		* IMPORTANT -
		*  - containers should set min height of view to height of html component because there is no scroll mask support atm
		*  - we can fix this by wrapping a mask "div" that clips the content around the main div or iframe
		*  - there are some problems with this approach such as handling scrollbars
		*/
		public function htmlScrollHandler(event:ScrollEvent):void {
			scrollEvent = event;
			var lineScrollSize:int = 0;
			var pageScrollSize:int = 0;
			
			if (!htmlCreated) return;
			
			//if (scrollEvent.direction == "horizontal" && scrollEvent.position >= 0) {
			if (scrollEvent.direction == "horizontal") {
				// if parent uses vertical layout 
				ExternalInterface.call(MOVE, id, contentLeft, null);
				
				// if parent is application and uses absolute layout
			}
			else if (scrollEvent.direction == "vertical") {
				// get scroll sizes. do not use Application.application.verticalLineScrollSize not accurate on line up
				lineScrollSize = event.currentTarget['verticalScrollBar']['lineScrollSize'];
				pageScrollSize = event.currentTarget['verticalScrollBar']['pageScrollSize'];
				
				var newPosition:int = 0;
				var scrollDetail:String = scrollEvent.detail;
				
				// check what part of the scrollbar user is using
				if (scrollDetail == ScrollEventDetail.THUMB_TRACK) {
					newPosition = contentTop;
					_updateScrollInterval++;
					
					// prevent update from happening ten times per drag (update event is generated by scroll)
					// turned off because it doesn't track - will investigate another time
					if (_updateScrollInterval < lineScrollSize) {
						//return;
					}
					
				}
				else if(scrollDetail == ScrollEventDetail.LINE_UP) {
					newPosition = contentTop + lineScrollSize;
				}
				else if(scrollDetail == ScrollEventDetail.LINE_DOWN) {
					newPosition = contentTop - lineScrollSize;
				}
				else if(scrollDetail == ScrollEventDetail.PAGE_UP) {
					newPosition = contentTop + lineScrollSize;
				}
				else if(scrollDetail == ScrollEventDetail.PAGE_DOWN) {
					newPosition = contentTop - lineScrollSize;
				}
				else if(scrollDetail == ScrollEventDetail.THUMB_POSITION) {
					newPosition = contentTop;
				}
				else {
					newPosition = contentTop;
				}
				
				// do not update unless the position has moved
				if (_previousScrollPosition != newPosition) {
					ExternalInterface.call(MOVE, id, null, newPosition);
					_previousScrollPosition = newPosition;
					_updateScrollInterval = lineScrollSize - 1;
				}
			}
		}
		
		private var _previousScrollPosition:int = 0;
		private var _updateScrollInterval:int = 0;
		
		/**
		* Scroll event class. Could refactor this variables usage.
		*/
		protected var scrollEvent:ScrollEvent = new ScrollEvent(ScrollEvent.SCROLL);
	
		// Not used
		protected function scrollEventHandler(val:int):void {
			
		}
	
		/**
		* Specifies if the HTML element has been created. 
		*/
		public var htmlCreated:Boolean = false;
	
		/**
		 * Returns the absolute distance of this component from the top edge of the Application
		 */
		public function get contentTop():Number {
			
			var topPosition:int = 0;
			var pos2:int = 0;
			var locationPoint:Point = new Point(0, 0);
			locationPoint = localToGlobal(locationPoint);
			
			var topValue:Number = Number(locationPoint.y + borderMetrics.top);
			//return topValue; OLD
			topPosition = this.localToGlobal(new Point(0,0)).y + borderMetrics.top;
			
			// new as of V4.2
			return topPosition;
		}
		
		/**
		 * Returns the absolute distance of this component from the left edge of the Application 
		 */
		public function get contentLeft():Number {
			var leftPosition:int = 0;
			var locationPoint:Point = new Point(x, y);
			var offset:int = 0;
			
			if (parent != Application.application) {
				locationPoint = localToGlobal(locationPoint);
				offset = x;
			}
			
			var leftValue:int = Math.round(locationPoint.x + borderMetrics.left - offset 
											- parentApplication.horizontalScrollPosition);
	 
			//return leftValue; OLD
			
			// new as of V4.2
			leftPosition = this.localToGlobal(new Point(0,0)).x + borderMetrics.left;
			return leftPosition;
		}
	
		/**
		 * Returns the viewMetrics width.
		 */
		public function get contentWidth():Number
		{
			return Math.round(width - borderMetrics.left - borderMetrics.right);
		}	
	
		/**
		 * Returns the viewMetrics height.
		 */
		public function get contentHeight():Number
		{
			return Math.round(height - borderMetrics.top - borderMetrics.bottom);
		}
		
		/**
		* Sets the url of an iframe. Cannot resize to fit the HTML element with pages from other domains than the html wrapper. 
		*/
		[Bindable("sourceChanged")]
	    [Inspectable(type="String", category="General", name="Source", defaultValue="true")]
		public function set source(value:String):void {
			_source = value;
			
			if (!htmlCreated) return;
			
			var m:String = ExternalInterface.call(SOURCE, id, _source);
			dispatchEvent(new Event("sourceChanged"));
			
			// check if user wants to fit component to height of content
			if (!fitToContentHeight) return;
	
			var repeatCount:int = Math.ceil(getHeightTimeout/getHeightInterval);
			getHeightTimer.delay = getHeightInterval
	        getHeightTimer.repeatCount = repeatCount;
	        
	        if (getHeightTimer.running) getHeightTimer.reset();
	        getHeightTimer.start();
	        fitToElementHeight();
		}
		
		/**
		* Gets the source url for an iframe element. 
		*/
	    public function get source():String {
	    	return _source;
	    }
	    
	    private var _source:String = "about:blank";

	}
}